home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / yacc / flexyacc / aflex.lha / aflex / src / vstringB.a < prev    next >
Text File  |  1991-05-16  |  22KB  |  669 lines

  1.  
  2. -- UNIT: generic package body of VSTRINGS
  3. --
  4. -- FILES: vstring_body.a in publiclib
  5. --        related file is vstring_spec.a in publiclib
  6. --
  7. -- PURPOSE:  An implementation of the abstract data type "variable-length
  8. --           string."
  9. --
  10. -- DESCRIPTION:  This package provides a private type VSTRING.  VSTRING objects
  11. --               are "strings" that have a length between zero and LAST, where
  12. --               LAST is the generic parameter supplied in the package
  13. --               instantiation.
  14. --
  15. --               In addition to the type VSTRING, a subtype and two constants
  16. --               are declared.  The subtype STRINDEX is an index to a VSTRING,
  17. --               The STRINDEX constant FIRST is an index to the first character
  18. --               of the string, and the VSTRING constant NUL is a VSTRING of
  19. --               length zero.  NUL is the default initial value of a VSTRING.
  20. --
  21. --               The following sets of functions, procedures, and operators
  22. --               are provided as operations on the type VSTRING:
  23. --
  24. --               ATTRIBUTE FUNCTIONS:  LEN, MAX, STR, CHAR
  25. --                 The attribute functions return the characteristics of
  26. --                 a VSTRING.
  27. --
  28. --               COMPARISON OPERATORS: "=", "/=", "<", ">", "<=", ">="
  29. --                 The comparison operators are the same as for the predefined
  30. --                 type STRING.
  31. --
  32. --               INPUT/OUTPUT PROCEDURES: GET, GET_LINE, PUT, PUT_LINE
  33. --                                        
  34. --                 The input/output procedures are similar to those for the
  35. --                 predefined type STRING, with the following exceptions:
  36. --
  37. --                   - GET has an optional parameter LENGTH, which indicates
  38. --                     the number of characters to get (default is LAST).
  39. --
  40. --                   - GET_LINE does not have a parameter to return the length
  41. --                     of the string (the LEN function should be used instead).
  42. --
  43. --               EXTRACTION FUNCTIONS: SLICE, SUBSTR, DELETE
  44. --                 The SLICE function returns the slice of a VSTRING between
  45. --                 two indices (equivalent to STR(X)(A .. B)).
  46. --
  47. --                 SUBSTR returns a substring of a VSTRING taken from a given
  48. --                 index and extending a given length.
  49. --
  50. --                 The DELETE function returns the VSTRING which results from
  51. --                 removing the slice between two indices.
  52. --
  53. --               EDITING FUNCTIONS: INSERT, APPEND, REPLACE
  54. --                 The editing functions return the VSTRING which results from
  55. --                 inserting, appending, or replacing at a given index with a
  56. --                 VSTRING, STRING, or CHARACTER.  The index must be in the
  57. --                 current range of the VSTRING; i.e., zero cannot be used.
  58. --
  59. --               CONCATENATION OPERATOR:  "&"
  60. --                 The concatenation operator is the same as for the type
  61. --                 STRING.  It should be used instead of APPEND when the
  62. --                 APPEND would always be after the last character.
  63. --
  64. --               POSITION FUNCTIONS: INDEX, RINDEX
  65. --                 The position functions return an index to the Nth occurrence
  66. --                 of a VSTRING, STRING, or CHARACTER from the front or back
  67. --                 of a VSTRING.  Zero is returned if the search is not
  68. --                 successful.
  69. --
  70. --               CONVERSION FUNCTIONS AND OPERATOR: VSTR, CONVERT, "+"
  71. --                 VSTR converts a STRING or a CHARACTER to a VSTRING.
  72. --
  73. --                 CONVERT is a generic function which can be instantiated to
  74. --                 convert from any given variable-length string to another,
  75. --                 provided the FROM type has a function equivelent to STR
  76. --                 defined for it, and that the TO type has a function equiv-
  77. --                 elent to VSTR defined for it.  This provides a means for
  78. --                 converting between VSTRINGs declared in separate instant-
  79. --                 iations of VSTRINGS.  When instantiating CONVERT for 
  80. --                 VSTRINGs, the STR and VSTR functions are implicitly defined,
  81. --                 provided that they have been made visible (by a use clause).
  82. --
  83. --                 Note:  CONVERT is NOT implicitly associated with the type 
  84. --                 VSTRING declared in this package (since it would not be a
  85. --                 derivable function (see RM 3.4(11))).
  86. --
  87. --                 Caution:  CONVERT cannot be instantiated directly with the
  88. --                 names VSTR and STR, since the name of the subprogram being
  89. --                 declared would hide the generic parameters with the same
  90. --                 names (see RM 8.3(16)).  CONVERT can be instantiated with
  91. --                 the operator "+", and any instantiation of CONVERT can
  92. --                 subsequently be renamed VSTR or STR.
  93. --
  94. --                 Example:  Given two VSTRINGS instantiations X and Y:
  95. --                   function "+" is new X.CONVERT(X.VSTRING, Y.VSTRING);
  96. --                   function "+" is new X.CONVERT(Y.VSTRING, X.VSTRING);
  97. --
  98. --                   (Y.CONVERT could have been used in place of X.CONVERT)
  99. --
  100. --                   function VSTR(A : X.VSTRING) return Y.VSTRING renames "+";
  101. --                   function VSTR(A : Y.VSTRING) return X.VSTRING renames "+";
  102. --
  103. --                 "+" is equivelent to VSTR.  It is supplied as a short-hand
  104. --                 notation for the function.  The "+" operator cannot immed-
  105. --                 iately follow the "&" operator; use ... & (+ ...) instead.
  106. pragma PAGE;
  107.  
  108. --  DISCUSSION:
  109. --
  110. --    This package implements the type "variable-length string" (vstring)
  111. --    using generics.  The alternative approaches are to use a discriminant 
  112. --    record in which the discriminant controls the length of a STRING inside
  113. --    the record, or a record containing an access type which points to a
  114. --      string, which can be deallocated and reallocated when necessary.
  115. --
  116. --    Advantages of this package:
  117. --      * The other approaches force the vstring to be a limited private 
  118. --          type.  Thus, their vstrings cannot appear on the left side of
  119. --          the assignment operator; ie., their vstrings cannot be given
  120. --          initial values or values by direct assignment.  This package
  121. --          uses a private type; therefore, these things can be done.
  122. --         
  123. --      * The other approach stores the vstring in a string whose length
  124. --        is determined dynamically.  This package uses a fixed length 
  125. --          string.  This difference might be reflected in faster and more
  126. --          consistent execution times (this has NOT been verified).
  127. --
  128. --    Disadvantages of this package:
  129. --      * Different instantiations must be used to declare vstrings with
  130. --        different maximum lengths (this may be desirable, since
  131. --        CONSTRAINT_ERROR will be raised if the maximum is exceeded).
  132. --
  133. --      * A second declaration is required to give the type declared by
  134. --        the instantiation a name other than "VSTRING."
  135. --
  136. --      * The storage required for a vstring is determined by the generic
  137. --        parameter LAST and not the actual length of its contents.  Thus,
  138. --          each object is allocated the maximum amount of storage, regardless
  139. --          of its actual size.
  140. --
  141. --  MISCELLANEOUS:
  142. --     Constraint checking is done explicitly in the code; thus, it cannot
  143. --     be suppressed.  On the other hand, constraint checking is not lost
  144. --     if pragma suppress is supplied to the compilation (-S option) 
  145. --     (The robustness of the explicit constraint checking has NOT been 
  146. --     determined).
  147. --
  148. --     Compiling with the optimizer (-O option) may significantly reduce
  149. --     the size (and possibly execution time) of the resulting executable.
  150. --
  151. --     Compiling an instantiation of VSTRINGS is roughly equivelent to
  152. --     recompiling VSTRINGS.  Since this takes a significant amount of time,
  153. --     and the instantiation does not depend on any other library units,
  154. --     it is STRONGLY recommended that the instantiation be compiled
  155. --     separately, and thus done only ONCE.
  156. --
  157. --  USAGE: with VSTRINGS;
  158. --         package package_name is new VSTRINGS(maximum_length);
  159. -- .......................................................................... --
  160. pragma PAGE;
  161.  
  162. package body VSTRINGS is
  163.  
  164.   -- local declarations
  165.  
  166.   FILL_CHAR : constant CHARACTER := ASCII.NUL;
  167.  
  168.   procedure FORMAT(THE_STRING : in out VSTRING; OLDLEN : in STRINDEX := LAST) is
  169.     -- fill the string with FILL_CHAR to null out old values
  170.  
  171.     begin -- FORMAT (Local Procedure)
  172.       THE_STRING.VALUE(THE_STRING.LEN + 1 .. OLDLEN) := 
  173.                                         (others => FILL_CHAR);
  174.     end FORMAT;
  175.  
  176.  
  177.   -- bodies of visible operations
  178.  
  179.   function LEN(FROM : VSTRING) return STRINDEX is
  180.  
  181.     begin -- LEN
  182.       return(FROM.LEN);
  183.     end LEN;
  184.  
  185.  
  186.   function MAX(FROM : VSTRING) return STRINDEX is
  187.     begin -- MAX
  188.       return(LAST);
  189.     end MAX;
  190.  
  191.  
  192.   function STR(FROM : VSTRING) return STRING is
  193.     begin -- STR
  194.       return(FROM.VALUE(FIRST .. FROM.LEN));
  195.     end STR;
  196.  
  197.  
  198.   function CHAR(FROM : VSTRING; POSITION : STRINDEX := FIRST)
  199.                  return CHARACTER is
  200.  
  201.     begin -- CHAR
  202.       if POSITION not in FIRST .. FROM.LEN
  203.         then raise CONSTRAINT_ERROR;
  204.        end if;
  205.       return(FROM.VALUE(POSITION));
  206.     end CHAR;
  207.  
  208.  
  209.   function "<" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
  210.     begin -- "<"
  211.       return(LEFT.VALUE < RIGHT.VALUE);
  212.     end "<";
  213.  
  214.  
  215.   function ">" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
  216.     begin -- ">"
  217.       return(LEFT.VALUE > RIGHT.VALUE);
  218.     end ">";
  219.  
  220.  
  221.   function "<=" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
  222.     begin -- "<="
  223.       return(LEFT.VALUE <= RIGHT.VALUE);
  224.     end "<=";
  225.  
  226.  
  227.   function ">=" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
  228.     begin -- ">="
  229.       return(LEFT.VALUE >= RIGHT.VALUE);
  230.     end ">=";
  231.  
  232.  
  233.   procedure PUT(FILE : in FILE_TYPE; ITEM : in VSTRING) is
  234.     begin -- PUT
  235.       PUT(FILE, ITEM.VALUE(FIRST .. ITEM.LEN));
  236.     end PUT;
  237.  
  238.   procedure Put(ITEM : in VSTRING) is
  239.     begin -- PUT
  240.       PUT(ITEM.VALUE(FIRST .. ITEM.LEN));
  241.     end PUT;
  242.  
  243.  
  244.   procedure PUT_LINE(FILE : in FILE_TYPE; ITEM : in VSTRING) is
  245.     begin -- PUT_LINE
  246.       PUT_LINE(FILE, ITEM.VALUE(FIRST .. ITEM.LEN));
  247.     end PUT_LINE;
  248.  
  249.   procedure PUT_LINE(ITEM : in VSTRING) is
  250.     begin -- PUT_LINE
  251.       PUT_LINE(ITEM.VALUE(FIRST .. ITEM.LEN));
  252.     end PUT_LINE;
  253.  
  254.  
  255.   procedure GET(FILE : in FILE_TYPE; ITEM : out VSTRING;
  256.                 LENGTH : in STRINDEX := LAST) is
  257.     begin -- GET
  258.       if LENGTH not in FIRST .. LAST
  259.         then raise CONSTRAINT_ERROR;
  260.        end if;
  261.  
  262.       ITEM := NUL;
  263.       for INDEX in FIRST .. LENGTH loop
  264.         GET(FILE, ITEM.VALUE(INDEX));
  265.         ITEM.LEN := INDEX;
  266.        end loop;
  267.     end GET;
  268.  
  269.   procedure GET(ITEM : out VSTRING; LENGTH : in STRINDEX := LAST) is
  270.     begin -- GET
  271.       if LENGTH not in FIRST .. LAST
  272.         then raise CONSTRAINT_ERROR;
  273.        end if;
  274.  
  275.       ITEM := NUL;
  276.       for INDEX in FIRST .. LENGTH loop
  277.         GET(ITEM.VALUE(INDEX));
  278.         ITEM.LEN := INDEX;
  279.        end loop;
  280.     end GET;
  281.  
  282.  
  283.   procedure GET_LINE(FILE : in FILE_TYPE; ITEM : in out VSTRING) is
  284.  
  285.     OLDLEN : constant STRINDEX := ITEM.LEN;
  286.  
  287.     begin -- GET_LINE
  288.       GET_LINE(FILE, ITEM.VALUE, ITEM.LEN);
  289.       FORMAT(ITEM, OLDLEN);
  290.     end GET_LINE;
  291.        
  292.   procedure GET_LINE(ITEM : in out VSTRING) is
  293.  
  294.     OLDLEN : constant STRINDEX := ITEM.LEN;
  295.  
  296.     begin -- GET_LINE
  297.       GET_LINE(ITEM.VALUE, ITEM.LEN);
  298.       FORMAT(ITEM, OLDLEN);
  299.     end GET_LINE;
  300.  
  301.  
  302.   function SLICE(FROM : VSTRING; FRONT, BACK : STRINDEX) return VSTRING is
  303.  
  304.     begin -- SLICE
  305.       if ((FRONT not in FIRST .. FROM.LEN) or else 
  306.          (BACK not in FIRST .. FROM.LEN)) and then FRONT <= BACK
  307.         then raise CONSTRAINT_ERROR;
  308.        end if;
  309.  
  310.       return(Vstr(FROM.VALUE(FRONT .. BACK)));
  311.     end SLICE;
  312.  
  313.  
  314.   function SUBSTR(FROM : VSTRING; START, LENGTH : STRINDEX) return VSTRING is
  315.  
  316.     begin -- SUBSTR
  317.       if (START not in FIRST .. FROM.LEN) or else
  318.          ((START + LENGTH - 1 not in FIRST .. FROM.LEN)
  319.           and then (LENGTH > 0))
  320.         then raise CONSTRAINT_ERROR;
  321.        end if;
  322.  
  323.       return(Vstr(FROM.VALUE(START .. START + LENGTH -1)));
  324.     end SUBSTR;
  325.  
  326.  
  327.   function DELETE(FROM : VSTRING; FRONT, BACK : STRINDEX) return VSTRING is
  328.  
  329.     TEMP : VSTRING := FROM;
  330.  
  331.     begin -- DELETE
  332.       if ((FRONT not in FIRST .. FROM.LEN) or else
  333.          (BACK not in FIRST .. FROM.LEN)) and then FRONT <= BACK
  334.         then raise CONSTRAINT_ERROR;
  335.        end if;
  336.  
  337.       if FRONT > BACK then return(FROM); end if;
  338.       TEMP.LEN := FROM.LEN - (BACK - FRONT) - 1;
  339.  
  340.       TEMP.VALUE(FRONT .. TEMP.LEN) := FROM.VALUE(BACK + 1 .. FROM.LEN);
  341.       FORMAT(TEMP, FROM.LEN);
  342.       return(TEMP);
  343.     end DELETE;
  344.  
  345.  
  346.   function INSERT(TARGET: VSTRING; ITEM: VSTRING;
  347.                   POSITION : STRINDEX := FIRST) return VSTRING is
  348.  
  349.     TEMP : VSTRING;
  350.  
  351.     begin -- INSERT
  352.       if POSITION not in FIRST .. TARGET.LEN
  353.         then raise CONSTRAINT_ERROR;
  354.        end if;
  355.  
  356.       if TARGET.LEN + ITEM.LEN > LAST
  357.         then raise CONSTRAINT_ERROR;
  358.         else TEMP.LEN := TARGET.LEN + ITEM.LEN;
  359.        end if;
  360.  
  361.       TEMP.VALUE(FIRST .. POSITION - 1) := TARGET.VALUE(FIRST .. POSITION - 1);
  362.       TEMP.VALUE(POSITION .. (POSITION + ITEM.LEN - 1)) :=
  363.         ITEM.VALUE(FIRST .. ITEM.LEN);
  364.       TEMP.VALUE((POSITION + ITEM.LEN) .. TEMP.LEN) :=
  365.         TARGET.VALUE(POSITION .. TARGET.LEN);
  366.  
  367.       return(TEMP);
  368.     end INSERT;
  369.  
  370.   function INSERT(TARGET: VSTRING; ITEM: STRING;
  371.                   POSITION : STRINDEX := FIRST) return VSTRING is
  372.     begin -- INSERT
  373.       return INSERT(TARGET, VSTR(ITEM), POSITION);
  374.     end INSERT;
  375.   
  376.   function INSERT(TARGET: VSTRING; ITEM: CHARACTER;
  377.                   POSITION : STRINDEX := FIRST) return VSTRING is
  378.     begin -- INSERT
  379.       return INSERT(TARGET, VSTR(ITEM), POSITION);
  380.     end INSERT;
  381.  
  382.  
  383.   function APPEND(TARGET: VSTRING; ITEM: VSTRING; POSITION : STRINDEX)
  384.                   return VSTRING is
  385.  
  386.     TEMP : VSTRING;
  387.     POS : STRINDEX := POSITION;
  388.  
  389.     begin -- APPEND
  390.       if POSITION not in FIRST .. TARGET.LEN
  391.         then raise CONSTRAINT_ERROR;
  392.        end if;
  393.  
  394.       if TARGET.LEN + ITEM.LEN > LAST
  395.         then raise CONSTRAINT_ERROR;
  396.         else TEMP.LEN := TARGET.LEN + ITEM.LEN;
  397.        end if;
  398.  
  399.       TEMP.VALUE(FIRST .. POS) := TARGET.VALUE(FIRST .. POS);
  400.       TEMP.VALUE(POS + 1 .. (POS + ITEM.LEN)) := ITEM.VALUE(FIRST .. ITEM.LEN);
  401.       TEMP.VALUE((POS + ITEM.LEN + 1) .. TEMP.LEN) :=
  402.         TARGET.VALUE(POS + 1 .. TARGET.LEN);
  403.  
  404.       return(TEMP);
  405.     end APPEND;
  406.  
  407.   function APPEND(TARGET: VSTRING; ITEM: STRING; POSITION : STRINDEX)
  408.                   return VSTRING is
  409.     begin -- APPEND
  410.       return APPEND(TARGET, VSTR(ITEM), POSITION);
  411.     end APPEND;
  412.  
  413.   function APPEND(TARGET: VSTRING; ITEM: CHARACTER; POSITION : STRINDEX)
  414.                   return VSTRING is
  415.     begin -- APPEND
  416.       return APPEND(TARGET, VSTR(ITEM), POSITION);
  417.     end APPEND;
  418.  
  419.  
  420.   function APPEND(TARGET: VSTRING; ITEM: VSTRING) return VSTRING is
  421.     begin -- APPEND
  422.       return(APPEND(TARGET, ITEM, TARGET.LEN));
  423.     end APPEND;
  424.  
  425.   function APPEND(TARGET: VSTRING; ITEM: STRING) return VSTRING is
  426.     begin -- APPEND
  427.       return(APPEND(TARGET, VSTR(ITEM), TARGET.LEN));
  428.     end APPEND;
  429.  
  430.   function APPEND(TARGET: VSTRING; ITEM: CHARACTER) return VSTRING is
  431.     begin -- APPEND
  432.       return(APPEND(TARGET, VSTR(ITEM), TARGET.LEN));
  433.     end APPEND;
  434.  
  435.  
  436.   function REPLACE(TARGET: VSTRING; ITEM: VSTRING;
  437.                    POSITION : STRINDEX := FIRST) return VSTRING is
  438.  
  439.     TEMP : VSTRING;
  440.  
  441.     begin -- REPLACE
  442.       if POSITION not in FIRST .. TARGET.LEN
  443.         then raise CONSTRAINT_ERROR;
  444.        end if;
  445.  
  446.       if POSITION + ITEM.LEN - 1 <= TARGET.LEN
  447.         then TEMP.LEN := TARGET.LEN;
  448.         elsif POSITION + ITEM.LEN - 1 > LAST
  449.           then raise CONSTRAINT_ERROR;
  450.           else TEMP.LEN := POSITION + ITEM.LEN - 1;
  451.        end if;
  452.  
  453.       TEMP.VALUE(FIRST .. POSITION - 1) := TARGET.VALUE(FIRST .. POSITION - 1);
  454.       TEMP.VALUE(POSITION .. (POSITION + ITEM.LEN - 1)) := 
  455.         ITEM.VALUE(FIRST .. ITEM.LEN);
  456.       TEMP.VALUE((POSITION + ITEM.LEN) .. TEMP.LEN) :=
  457.         TARGET.VALUE((POSITION + ITEM.LEN) .. TARGET.LEN);
  458.  
  459.       return(TEMP);
  460.     end REPLACE;
  461.  
  462.   function REPLACE(TARGET: VSTRING; ITEM: STRING;
  463.                    POSITION : STRINDEX := FIRST) return VSTRING is
  464.     begin -- REPLACE
  465.       return REPLACE(TARGET, VSTR(ITEM), POSITION);
  466.     end REPLACE;
  467.  
  468.   function REPLACE(TARGET: VSTRING; ITEM: CHARACTER;
  469.                    POSITION : STRINDEX := FIRST) return VSTRING is
  470.     begin -- REPLACE
  471.       return REPLACE(TARGET, VSTR(ITEM), POSITION);
  472.     end REPLACE;
  473.  
  474.  
  475.   function "&"(LEFT:VSTRING; RIGHT : VSTRING) return VSTRING is
  476.  
  477.     TEMP : VSTRING;
  478.  
  479.     begin -- "&"
  480.       if LEFT.LEN + RIGHT.LEN > LAST
  481.         then raise CONSTRAINT_ERROR;
  482.         else TEMP.LEN := LEFT.LEN + RIGHT.LEN;
  483.        end if;
  484.  
  485.       TEMP.VALUE(FIRST .. TEMP.LEN) := LEFT.VALUE(FIRST .. LEFT.LEN) &
  486.         RIGHT.VALUE(FIRST .. RIGHT.LEN);
  487.       return(TEMP);
  488.     end "&";
  489.  
  490.   function "&"(LEFT:VSTRING; RIGHT : STRING) return VSTRING is
  491.     begin -- "&"
  492.       return LEFT & VSTR(RIGHT);
  493.     end "&";
  494.  
  495.   function "&"(LEFT:VSTRING; RIGHT : CHARACTER) return VSTRING is
  496.     begin -- "&"
  497.       return LEFT & VSTR(RIGHT);
  498.     end "&";
  499.  
  500.   function "&"(LEFT : STRING; RIGHT : VSTRING) return VSTRING is
  501.     begin -- "&"
  502.       return VSTR(LEFT) & RIGHT;
  503.     end "&";
  504.  
  505.   function "&"(LEFT : CHARACTER; RIGHT : VSTRING) return VSTRING is
  506.     begin -- "&"
  507.       return VSTR(LEFT) & RIGHT;
  508.     end "&";
  509.  
  510.  
  511.   Function INDEX(WHOLE : VSTRING; PART : VSTRING; OCCURRENCE : NATURAL := 1)
  512.                  return STRINDEX is
  513.  
  514.     NOT_FOUND : constant NATURAL := 0;
  515.     INDEX : NATURAL := FIRST;
  516.     COUNT : NATURAL := 0;
  517.  
  518.     begin -- INDEX
  519.       if PART = NUL then return(NOT_FOUND); -- by definition
  520.         end if;
  521.  
  522.       while INDEX + PART.LEN - 1 <= WHOLE.LEN and then COUNT < OCCURRENCE loop
  523.         if WHOLE.VALUE(INDEX .. PART.LEN + INDEX - 1) =
  524.            PART.VALUE(1 .. PART.LEN)
  525.           then COUNT := COUNT + 1;
  526.          end if;
  527.         INDEX := INDEX + 1;
  528.        end loop;
  529.  
  530.       if COUNT = OCCURRENCE
  531.         then return(INDEX - 1);
  532.         else return(NOT_FOUND);
  533.        end if;
  534.     end INDEX;
  535.  
  536.   Function INDEX(WHOLE : VSTRING; PART : STRING; OCCURRENCE : NATURAL := 1)
  537.                  return STRINDEX is
  538.  
  539.     begin -- Index
  540.       return(Index(WHOLE, VSTR(PART), OCCURRENCE));
  541.     end INDEX;
  542.  
  543.  
  544.   Function INDEX(WHOLE : VSTRING; PART : CHARACTER; OCCURRENCE : NATURAL := 1)
  545.                  return STRINDEX is
  546.  
  547.     begin -- Index
  548.       return(Index(WHOLE, VSTR(PART), OCCURRENCE));
  549.     end INDEX;
  550.  
  551.  
  552.   function RINDEX(WHOLE: VSTRING; PART:VSTRING; OCCURRENCE:NATURAL := 1) 
  553.                  return STRINDEX is
  554.  
  555.     NOT_FOUND : constant NATURAL := 0;
  556.     INDEX : INTEGER := WHOLE.LEN - (PART.LEN -1);
  557.     COUNT : NATURAL := 0;
  558.  
  559.     begin -- RINDEX
  560.       if PART = NUL then return(NOT_FOUND); -- by definition
  561.         end if;
  562.  
  563.       while INDEX >= FIRST and then COUNT < OCCURRENCE loop
  564.         if WHOLE.VALUE(INDEX .. PART.LEN + INDEX - 1) =
  565.            PART.VALUE(1 .. PART.LEN)
  566.           then COUNT := COUNT + 1;
  567.          end if;
  568.         INDEX := INDEX - 1;
  569.        end loop;
  570.  
  571.       if COUNT = OCCURRENCE
  572.         then
  573.           if COUNT > 0
  574.             then return(INDEX + 1);
  575.             else return(NOT_FOUND);
  576.            end if;
  577.         else return(NOT_FOUND);
  578.        end if;
  579.     end RINDEX;
  580.  
  581.   Function RINDEX(WHOLE : VSTRING; PART : STRING; OCCURRENCE : NATURAL := 1)
  582.                  return STRINDEX is
  583.  
  584.     begin -- Rindex
  585.       return(RINDEX(WHOLE, VSTR(PART), OCCURRENCE));
  586.     end RINDEX;
  587.  
  588.  
  589.   Function RINDEX(WHOLE : VSTRING; PART : CHARACTER; OCCURRENCE : NATURAL := 1)
  590.                  return STRINDEX is
  591.  
  592.     begin -- Rindex
  593.       return(RINDEX(WHOLE, VSTR(PART), OCCURRENCE));
  594.     end RINDEX;
  595.  
  596.  
  597.   function VSTR(FROM : CHARACTER) return VSTRING is
  598.     
  599.     TEMP : VSTRING;
  600.  
  601.     begin -- VSTR
  602.       if LAST < 1
  603.         then raise CONSTRAINT_ERROR;
  604.         else TEMP.LEN := 1;
  605.        end if;
  606.  
  607.       TEMP.VALUE(FIRST) := FROM;
  608.       return(TEMP);
  609.     end VSTR;
  610.  
  611.  
  612.   function VSTR(FROM : STRING) return VSTRING is
  613.  
  614.     TEMP : VSTRING;
  615.  
  616.     begin -- VSTR
  617.       if FROM'LENGTH > LAST
  618.         then raise CONSTRAINT_ERROR;
  619.         else TEMP.LEN := FROM'LENGTH;
  620.        end if;
  621.  
  622.       TEMP.VALUE(FIRST .. FROM'LENGTH) := FROM;
  623.       return(TEMP);
  624.     end VSTR;
  625.  
  626.   Function "+" (FROM : STRING) return VSTRING is
  627.     begin -- "+"
  628.       return(VSTR(FROM));
  629.     end "+";
  630.  
  631.   Function "+" (FROM : CHARACTER) return VSTRING is
  632.     begin
  633.      return(VSTR(FROM));
  634.     end "+";
  635.  
  636.  
  637.   function CONVERT(X : FROM) return TO is
  638.  
  639.     begin -- CONVERT
  640.       return(VSTR(STR(X)));
  641.     end CONVERT;   
  642. end VSTRINGS;
  643. -- .......................................................................... --
  644. --
  645. -- DISTRIBUTION AND COPYRIGHT:
  646. --                                                           
  647. -- This software is released to the Public Domain (note:
  648. --   software released to the Public Domain is not subject
  649. --   to copyright protection).
  650. -- Restrictions on use or distribution:  NONE
  651. --                                                           
  652. -- DISCLAIMER:
  653. --                                                           
  654. -- This software and its documentation are provided "AS IS" and
  655. -- without any expressed or implied warranties whatsoever.
  656. -- No warranties as to performance, merchantability, or fitness
  657. -- for a particular purpose exist.
  658. --
  659. -- Because of the diversity of conditions and hardware under
  660. -- which this software may be used, no warranty of fitness for
  661. -- a particular purpose is offered.  The user is advised to
  662. -- test the software thoroughly before relying on it.  The user
  663. -- must assume the entire risk and liability of using this
  664. -- software.
  665. --
  666. -- In no event shall any person or organization of people be
  667. -- held responsible for any direct, indirect, consequential
  668. -- or inconsequential damages or lost profits.
  669.